﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net.NetworkInformation;
using System.Net;
using System.Threading;
using System.ComponentModel;
using System.Diagnostics;


namespace GDocUploader.Communication
{
    public class Operations
    {
        private static List<FAttente> FileAttente = new List<FAttente>();
        private static List<erreur> StackLog = new List<erreur>();
        private const String ExtensionsConnues = "pdf;ppt;pps;xls;csv;ods;txt;tsv;tsb;html;htm;doc;rtf;odt";

        /// <summary>
        /// Personnalise le nom du fichier
        /// </summary>
        /// <param name="name">Nom du Fichier</param>
        /// <returns>Le nom personnalisé du fichier</returns>
        public static string getfilename(string name)
        {
            String[] Extensions = ExtensionsConnues.Split(';');
            String[] NameComp = name.Split('.');
            if (NameComp.Length == 1) return name + "_";
            string ext = NameComp[NameComp.Length - 1].ToLower();
            bool trouve = false;
            foreach (string s in Extensions) if (s == ext) trouve = true;
            if (trouve) return name;
            else return name + "_";
        }

        /// <summary>
        /// Verifie le type d'un object
        /// </summary>
        /// <param name="chemin"> Chemin de l'objet</param>
        /// <returns>True s'il est valide</returns>
        public static bool isFile(string chemin)
        {
            try
            {
                FileInfo F = new FileInfo(chemin);
                foreach (String s in Directory.GetFiles(F.FullName))
                { }
                foreach (String S in Directory.GetDirectories(F.FullName))
                { }
                return false;
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// Etablie un contrôle de taille sur le fichier
        /// </summary>
        /// <param name="chemin">Chemin du Fichier</param>
        /// <returns>True s'il est valide</returns>
        public static bool IsUploadValide(String chemin)
        {
            if (!isFile(chemin)) return true;
            FileInfo F = new FileInfo(chemin);
            if (!F.Exists)
            {
                return false;
            }
            switch (F.Extension.ToLower())
            {
                case "pdf":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                     
                        return false;
                    }
                     
                    break;
                case "ppt":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                       
                        return false;
                    }
                    break;
                case "pps":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                      
                        return false;
                    }
                    break;
                case "xls":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                       
                        return false;
                    }
                    break;
                case "xlsx":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                       
                        return false;
                    }
                    break;
                case "csv":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                      
                        return false;
                    }
                    break;
                case "ods":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                       
                        return false;
                    }
                    break;
                case "txt":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                        
                        return false;
                    }
                    break;
                case "tsv":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                       
                        return false;
                    }
                    break;
                case "tsb":
                    if (F.Length > 10 * 1024 * 1024)
                    {
                       
                        return false;
                    }
                    break;
                default:
                    if (F.Length > 500 * 1024)
                    {
                       
                        return false;
                    }
                    break;
            }
            return true;

        }

        public static bool IsActiveConnexion()
        {
            try
            {
                Ping pingSender = new Ping();
                PingOptions options = new PingOptions();
                options.DontFragment = true;

                String data = new String('a', 32);
                byte[] buffer = Encoding.ASCII.GetBytes(data);
                int timeout = 120;

                IPHostEntry entry = Dns.GetHostEntry("www.google.com");
                PingReply reply = pingSender.Send(entry.AddressList[0], timeout, buffer, options);
                if (reply.Status == IPStatus.Success) return true;
                else return false;
            }
            catch
            {
                return false;
            }
        }

        public static void AddFile(FAttente F)
        {
            FileAttente.Add(F);
        }

        public static void RemoveFile(FAttente F)
        {
            FileAttente.Remove(F);
        }

        public static void AddEntry(erreur Entry)
        {
            StackLog.Add(Entry);
        }

        public static String GetRapport()
        {
            string retour = "";
            if (StackLog.Count == 0) return "Aucune erreur détectée";
            foreach (erreur er in StackLog)
            {
                retour += Environment.NewLine;
                retour += Environment.NewLine;
                retour += Environment.NewLine;
                retour += "Erreur N° : " + er.ID;
                retour += Environment.NewLine;
                retour += "Nom : " + er.nom;
                retour += Environment.NewLine;
                retour += "Date : " + er.DteErr;
                retour += Environment.NewLine;
                retour += "description : " + er.description;
            }
            return retour;
        }

        public static string getRepportAt(int index)
        {
            string retour = "";
            foreach (erreur er in StackLog)
            {
                if (er.ID == index)
                {
                    retour += Environment.NewLine;
                    retour += Environment.NewLine;
                    retour += Environment.NewLine;
                    retour += "Erreur N° : " + er.ID;
                    retour += Environment.NewLine;
                    retour += "Nom : " + er.nom;
                    retour += Environment.NewLine;
                    retour += "Date : " + er.DteErr;
                    retour += Environment.NewLine;
                    retour += "description : " + er.description;
                }
            }
            return retour;
        }

        public static Byte[] GetByte(String chemin)
        {
            if (!isFile(chemin)) return null;
            FileStream fs = File.OpenRead(chemin);
            byte[] data = new byte[fs.Length];
            fs.Read(data, 0, data.Length);
            return data;
        }

        public static string EnoceDerToString(byte[] Text)
        {
            char séparator = ';';
            string newText = "";
            if (Text == null) return newText;
            for (int i = 0; i < Text.Length; i++)
            {
                if (i == Text.Length - 1)
                    newText += Text[i];
                else
                    newText += Text[i] + séparator;
            }
            return newText;
        }
    }

    public class FAttente
    {
        public string fileName { get; set; }
        public bool isfile { get; set; }
        public string chemin { get; set; }
        public string PathTo { get; set; }
    }

    public class erreur
    {
        public int ID { get; set; }
        public string nom { get; set; }
        public string description { get; set; }
        public DateTime DteErr { get; set; }
    }

    public class Declacheur
    {
        private BackgroundWorker FileThread = new BackgroundWorker();
        private BackgroundWorker FolderThread = new BackgroundWorker();
        private FAttente F;

        public Declacheur(string chemin)
        {
            

           
            initialiseCompo();
          
            if (Operations.isFile(chemin))
            {
               

                if (!Operations.IsUploadValide(chemin))
                {
                    erreur er = new erreur();
                    Random R = new Random();
                    er.ID = R.Next();
                    er.nom = chemin;
                    er.DteErr = DateTime.Now;
                    er.description = "l'erreur peut être dû au inexistance du fichier" + Environment.NewLine + "ou qu'il ne verifie pas les conditions de taille";
                    Operations.AddEntry(er);
                    return;
                }
                else
                {
                  

                    F = new FAttente();
                    F.chemin = chemin;
                    F.PathTo = "";
                    F.isfile = true;
                    F.fileName = new FileInfo(chemin).Name;
                    Operations.AddFile(F);

                  

                    
                    FileThread.RunWorkerAsync();
                }
            }
            else
            {
               
             
                if (!Directory.Exists(chemin))
                {
                   
                   
                    erreur er = new erreur();
                    Random R = new Random();
                    er.ID = R.Next();
                    er.nom = chemin;
                    er.DteErr = DateTime.Now;
                    er.description = "Le Chemin " + chemin + " est invalide";
                    Operations.AddEntry(er);
                    return;
                }
                else
                {
                    F = new FAttente();
                    F.chemin = chemin;
                    F.PathTo = "";
                    F.isfile = false;
                    F.fileName = new FileInfo(chemin).Name;
                    Operations.AddFile(F);
                  
                
                    FolderThread.RunWorkerAsync();
                }
            }

        }

        public Declacheur(string chemin, String PathTo)
        {
            

          
            initialiseCompo();
          
            if (Operations.isFile(chemin))
            {
               

              
                if (!Operations.IsUploadValide(chemin))
                {
                    erreur er = new erreur();
                    Random R = new Random();
                    er.ID = R.Next();
                    er.nom = "Fichier Invalide";
                    er.DteErr = DateTime.Now;
                    er.description = "l'erreur peut être dû au inexistance du fichier" + Environment.NewLine + "ou qu'il ne verifie pas les conditions de taille";
                    Operations.AddEntry(er);
                    return;
                }
                else
                {
                  
                  
                    F = new FAttente();
                    F.chemin = chemin;
                    F.PathTo = PathTo;
                    F.isfile = true;
                    F.fileName = new FileInfo(chemin).Name;
                    Operations.AddFile(F);
               
                  
                    FileThread.RunWorkerAsync();
                }
            }
            else
            {
           

              
                if (!Directory.Exists(chemin))
                {
                 
                  
                    erreur er = new erreur();
                    Random R = new Random();
                    er.ID = R.Next();
                    er.nom = "Répertoire Invalide";
                    er.DteErr = DateTime.Now;
                    er.description = "Le Chemin " + chemin + " est invalide";
                    Operations.AddEntry(er);
                    return;
                }
                else
                {
                    F = new FAttente();
                    F.chemin = chemin;
                    F.PathTo = PathTo;
                    F.isfile = false;
                    F.fileName = new FileInfo(chemin).Name;
                    Operations.AddFile(F);
               
                 
                    FolderThread.RunWorkerAsync();
                }
            }

        }

        private void initialiseCompo()
        {
            //FileThread
            FileThread.DoWork += new DoWorkEventHandler(FileThread_DoWork);
            FileThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FileThread_RunWorkerCompleted);


            //FolderThread
            FolderThread.DoWork += new DoWorkEventHandler(FolderThread_DoWork);
            FolderThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FolderThread_RunWorkerCompleted);


        }

        private void FileThread_DoWork(object sender, DoWorkEventArgs e)
        {
            if (new FileInfo(F.chemin).Extension.Length == 0)
            {
                if (F.PathTo == "")
                {
                    new GDocUploader.Communication.FileS(F.chemin);
                }
                else
                {
                    new GDocUploader.Communication.FileS(F.chemin, F.PathTo);
                }
            }
            else
            {
                if (F.PathTo == "")
                {
                    new GDocUploader.Communication.FileS(F.chemin,true);
                }
                else
                {
                    new GDocUploader.Communication.FileS(F.chemin, F.PathTo,true);
                }
            }
           
        }

        private void FileThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Operations.RemoveFile(F);
            FileThread.Dispose();
        }


        private void FolderThread_DoWork(object sender, DoWorkEventArgs e)
        {
            if (F.PathTo == "")
            {
                GDocUploader.Communication.Folder xx =   new GDocUploader.Communication.Folder(F.chemin);
                while (!xx.fait) ;
                foreach (string s in Directory.GetDirectories(F.chemin))
                {
                    new Declacheur(s, F.fileName);
                }
                foreach (string s in Directory.GetFiles(F.chemin))
                {
                    new Declacheur(s, F.fileName);
                }

            }
            else
            {
                GDocUploader.Communication.Folder xx = new GDocUploader.Communication.Folder(F.chemin, F.PathTo);
                while (!xx.fait) ;
                foreach (string s in Directory.GetDirectories(F.chemin))
                {
                    new process1(start).BeginInvoke(s, F.PathTo + "/" + F.fileName,null,null);
                   
                    //new Declacheur(s, F.PathTo + "/" + F.fileName);
                }
                foreach (string s in Directory.GetFiles(F.chemin))
                {
                    new process1(start).BeginInvoke(s, F.PathTo + "/" + F.fileName, null, null);
                    //new Declacheur(s, F.PathTo + "/" + F.fileName);
                }
            }
        }

        public void start(string args1, string args2)
        {
            new Declacheur(args1, args2);
        }

        private delegate void process1(string args1, string args2);

        private void FolderThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Operations.RemoveFile(F);
            FolderThread.Dispose();
        }
    }

}
